package main

import (
	"bufio"
	"fmt"
	"io"
	"net"
	"os"
	"strings"
)

func main() {
	conn, err := net.Dial("tcp", "127.0.0.1:8080")
	if err != nil {
		fmt.Println("client dial err=", err)
		return
	}
	var r io.Reader = conn
	fmt.Printf("r type = %T , value = %v\n", r, r) // r type = *net.TCPConn , value = &{{0xc00009ca00}}

	var w io.Writer = conn
	fmt.Printf("w type = %T , value = %v\n", w, w) // w type = *net.TCPConn , value = &{{0xc00009ca00}}

	//功能一：客户端可以发送单行数据，然后就退出
	reader := bufio.NewReader(os.Stdin) //os.Stdin 代表标准输入[终端]

	for {

		//从终端读取一行用户输入，并准备发送给服务器
		line, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("readString err=", err)
		}
		//如果用户输入的是 exit就退出
		line = strings.Trim(line, " \r\n") // 去掉空格、\r \n字符
		if line == "exit" {
			fmt.Println("客户端退出..")
			break
		}

		//再将line 发送给 服务器
		// 1) 使用 conn  的原生方式
		// _, err = conn.Write([]byte(line + "\n"))
		// if err != nil {
		// 	fmt.Println("conn.Write err=", err)
		// }

		// 2) 包装为 bufio.Writer 方式，记得写完了要Flush
		writer := bufio.NewWriter(conn)
		_, err = writer.Write([]byte(line + "\n"))
		if err != nil {
			fmt.Println("conn.Write err=", err)
		}
		writer.Flush() // 一定要刷新！

		// 读服务端发的消息 （读消息和写消息一样有两种方式：1）原生conn的；2）包装为bufio.Reader；）
		// 这里能够使用 bufio.NewReader() 是因为 conn拥有一个fd *netFD成员，该成员通过一系列继承
		// 最终继承了Reader接口
		// 1) 使用conne的原生方式
		// byteBuff := make([]byte, 1024)
		// n, err := conn.Read(byteBuff)
		// if err != nil {
		// 	fmt.Printf("客户端退出 err=%v", err) // 客户端退出 err=EOF
		// 	return
		// }
		// recString := string(byteBuff[:n])
		// fmt.Printf("服务端： %v", recString)

		// 2) 使用 bufio.Reader封装
		status, err := bufio.NewReader(conn).ReadString('\n')
		if err != nil {
			fmt.Printf("服务端接受消息出错: %v", err)
		}
		fmt.Printf("服务端：%v", status)
	}
}
